package com.cee.util;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import javax.xml.datatype.XMLGregorianCalendar;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * The type Date util.
 */
public final class DateUtil {


    public static final String[][] strArray = {{"MONDAY", "一"}, {"TUESDAY", "二"}, {"WEDNESDAY", "三"}, {"THURSDAY", "四"}, {"FRIDAY", "五"}, {"SATURDAY", "六"}, {"SUNDAY", "日"}};

    /**
     * The constant DATE_HOUR_MIN_NOT_BLANK_PATTERN.
     */
    public static final String DATE_HOUR_MIN_NOT_BLANK_PATTERN = "dd/MM/yyyyHHmm";
    /**
     * The constant DATE_PATTERN.
     */
    public static final String DATE_PATTERN = "dd/MM/yyyy";

    /**
     * The constant DATE_TIME_PATTERN.
     */
    public static final String DATE_TIME_PATTERN = "dd/MM/yyyy HH:mm:ss";


    /**
     * The constant I18n Time Pattern
     */
    public static final String DATE_TIME_PATTERN_I18N = "yyyy-MM-dd HH:mm:ss";

    /**
     * The constant I18n Time Pattern
     */
    public static final String DATE_PATTERN_I18N = "yyyy-MM-dd";

    /**
     * The constant DATE_TIME_HM_PATTERN.
     */
    public static final String DATE_TIME_HM_PATTERN = "dd/MM/yyyy HH:mm";

    /**
     * The constant DATE_SYSTEM_PATTERN.
     */
    public static final String DATE_SYSTEM_PATTERN = "yyyyMMdd";

    /**
     * The constant DATE_TIME_SYSTEM_PATTERN.
     */
    public static final String DATE_TIME_SYSTEM_PATTERN = "yyyyMMddHHmmss";

    /**
     * The constant DATE_TIME_SYSTEM_PATTERN_QR_CODE.
     */
    public static final String DATE_TIME_SYSTEM_PATTERN_SUB_HOURS = "yyMMddHHmm";

    /**
     * DATE_TIME_SYSTEM_PATTERN_HOURS.
     */
    public static final String DATE_TIME_SYSTEM_PATTERN_HOURS = "yyyyMMddHH";
    /**
     * The constant TIME_PATTERN.
     */
    public static final String TIME_PATTERN = "HH:mm:ss";

    /**
     * The constant HM_PATTERN.
     */
    public static final String HM_PATTERN = "HHmm";

    /**
     * The constant YEAR_PATTERN.
     */
    public static final String YEAR_PATTERN = "yyyy";

    /**
     * The constant DATE_TIME_HM_SYSTEM_PATTERN.
     */
    public static final String DATE_TIME_HM_SYSTEM_PATTERN = "yyyyMMddHHmm";

    /**
     * The constant DATE_TIME_PATTERN_2.
     */
    public static final String DATE_TIME_PATTERN_2 = "yyyy/MM/dd HH:mm:ss";

    /**
     * The constant DATA_MONTH_YEAR_PATTERN.
     */
    public static final String DATA_MONTH_YEAR_PATTERN = "MM/yyyy";

    /**
     * The constant DATA_YEAR_MONTH_PATTERN.
     */
    public static final String DATA_YEAR_MONTH_PATTERN = "yyyyMM";

    /**
     * The constant DATE_YEAR_MONTH_PATTERN_SLASH.
     */
    public static final String DATE_YEAR_MONTH_PATTERN_SLASH = "yyyy/MM/dd";

    public static final String DATE_YEAR_MONTH_HM_PATTERN_SLASH = "yyyy/MM/dd HH:mm";

    /**
     * The constant DATE_TIME__FORMATTER_SYSTEM_PATTERN_SUB_HOURS.
     */
    public static final DateTimeFormatter DATE_TIME__FORMATTER_SYSTEM_PATTERN_SUB_HOURS = DateTimeFormatter.ofPattern(DATE_TIME_HM_PATTERN);

    /**
     * Sys time in system format string.
     *
     * @return the string
     */
    public static String sysTimeInSystemFormat() {
        return format(new Date(), DATE_TIME_SYSTEM_PATTERN);
    }

    /**
     * Trim time part date.
     *
     * @param date the date
     * @return the date
     */
    public static Date trimTimePart(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * Gets year.
     *
     * @param date the date
     * @return the year
     */
    public static Integer getYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        return cal.get(Calendar.YEAR);
    }

    /**
     * Gets day.
     *
     * @param date the date
     * @return the day
     */
    public static Integer getDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * Date equals boolean.
     *
     * @param date1 the date 1
     * @param date2 the date 2
     * @return the boolean
     */
    public static boolean dateEquals(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);

        if (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH)
                && cal1.get(Calendar.DATE) == cal2.get(Calendar.DATE)) {
            return true;
        }

        return false;
    }

    /**
     * Compare the date with startDate and endDate
     *
     * @param startDate the start date
     * @param endDate   the end date
     * @param date      the date
     * @return boolean boolean
     */
    public static boolean compareDate(Date startDate, Date endDate, Date date) {
        date = getDate(date);
        if (date.compareTo(getDate(startDate)) >= 0 && date.compareTo(getDate(endDate)) <= 0) {
            return true;
        }
        return false;
    }

    /**
     * 如果startDate 大於等於endDate，返回true,精確到日.
     *
     * @param startDate the start date
     * @param endDate   the end date
     * @return boolean boolean
     */
    public static boolean compareDate(Date startDate, Date endDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        int startDateVal = Integer.parseInt(simpleDateFormat.format(startDate));
        int endDateVal = Integer.parseInt(simpleDateFormat.format(endDate));
        return startDateVal >= endDateVal;
    }

    /**
     * 如果startDate 等于endDate，返回true,精確到日.
     *
     * @param startDate startDate
     * @param endDate   endDate
     * @return boolean boolean
     */
    public static boolean equalsDate(Date startDate, Date endDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        int startDateVal = Integer.parseInt(simpleDateFormat.format(startDate));
        int endDateVal = Integer.parseInt(simpleDateFormat.format(endDate));
        return startDateVal == endDateVal;
    }

    /**
     * 如果startDate 小于等于endDate，返回true,精確到日.
     *
     * @param startDate startDate
     * @param endDate   endDate
     * @return boolean boolean
     */
    public static boolean lessOrEqualsDate(Date startDate, Date endDate) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
        int startDateVal = Integer.parseInt(simpleDateFormat.format(startDate));
        int endDateVal = Integer.parseInt(simpleDateFormat.format(endDate));
        return startDateVal <= endDateVal;
    }


    /**
     * 如果startDate 大於endDate，返回true,精確到日.
     *
     * @param startDate the start date
     * @param endDate   the end date
     * @return boolean boolean
     */
    public static boolean compareDateNotEqual(Date startDate, Date endDate) {
        int startDateVal = Integer.parseInt(format(startDate, DATE_SYSTEM_PATTERN));
        int endDateVal = Integer.parseInt(format(endDate, DATE_SYSTEM_PATTERN));
        return startDateVal > endDateVal;
    }

    /**
     * Gets date.
     *
     * @param date the date
     * @return the date
     */
    public static Date getDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getTime();
    }

    /**
     * Gets month.
     *
     * @param date the date
     * @return the month
     */
    public static Integer getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH);
    }

    /**
     * Gets month last date.
     *
     * @param date the date
     * @return the month last date
     */
    public static Date getMonthLastDate(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return ca.getTime();
    }

    /**
     * 將字符串變成日期格式
     *
     * @param dateStr 日期格式的字符串
     * @return 日期類型 date
     */
    public static Date parse(String dateStr) {
        return parse(dateStr, DATE_PATTERN);
    }

    /**
     * Parse date.
     *
     * @param dateStr the date str
     * @param format  the format
     * @return the date
     */
    public static Date parse(String dateStr, String format) {
        try {
            return takeParse(dateStr, format);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static Date takeParse(String dateStr, String format) throws ParseException {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat(format);
        dateFormat.setLenient(false);
        return dateFormat.parse(dateStr);
    }

    /**
     * Parse local date time.
     *
     * @param dateStr           the date str
     * @param dateTimeFormatter the date time formatter
     * @return the local date time
     */
    public static LocalDateTime parse(final String dateStr, DateTimeFormatter dateTimeFormatter) {
        return LocalDateTime.parse(dateStr, dateTimeFormatter);
    }

    /**
     * Format string.
     *
     * @param date the date
     * @return the string
     */
    public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * Format datetime string.
     *
     * @param date the date
     * @return the string
     */
    public static String formatDatetime(Date date) {
        return format(date, DATE_TIME_PATTERN);
    }

    /**
     * Format string.
     *
     * @param date   the date
     * @param format the format
     * @return the string
     */
    public static String format(Date date, String format) {
        if (date == null || StringUtils.isBlank(format)) {
            return null;
        } else {
            SimpleDateFormat dataFormat = new SimpleDateFormat(format);
            return dataFormat.format(date);
        }
    }

    /**
     * Format string.
     *
     * @param dateTime the date time
     * @param format   the format
     * @return the string
     */
    public static String format(LocalDateTime dateTime, String format) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(format);
        return dateTime.format(dateTimeFormatter);
    }

    /**
     * 計算兩個日期之間相差的天數
     *
     * @param smdate 較小的時間
     * @param bdate  較大的時間
     * @return 相差天數 int
     * @throws ParseException the parse exception
     */
    public static int daysBetween(Date smdate, Date bdate)
            throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
        smdate = sdf.parse(sdf.format(smdate));
        bdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days = (time2 - time1) / (1000 * 3600 * 24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * Months between int.
     *
     * @param start the start
     * @param end   the end
     * @return the int
     */
    public static int monthsBetween(Date start, Date end) {
        Calendar c1 = GregorianCalendar.getInstance();
        Calendar c2 = GregorianCalendar.getInstance();
        c1.setTime(start);
        c2.setTime(end);
        if (c1.getTimeInMillis() < c2.getTimeInMillis()) {
            long milSeconds = c2.getTimeInMillis();
            c2.setTimeInMillis(c1.getTimeInMillis());
            c1.setTimeInMillis(milSeconds);
        }
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);

        int yearInterval = year1 - year2;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if (month1 < month2 || month1 == month2 && day1 < day2)
            yearInterval--;
        // 获取月数差值
        int monthInterval = (month1 + 12) - month2;
        if (day1 < day2)
            monthInterval--;
        monthInterval %= 12;
        return yearInterval * 12 + monthInterval;
    }

    /**
     * Years between double.
     *
     * @param start the start
     * @param end   the end
     * @return the double
     */
    public static double yearsBetween(Date start, Date end) {
        int monthsBetween = monthsBetween(start, end);
        BigDecimal years = new BigDecimal(monthsBetween);
        return years.divide(new BigDecimal(12), 2, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * Day plus date.
     *
     * @param date the date
     * @param plus the plus
     * @return the date
     * @throws ParseException the parse exception
     */
    public static Date dayPlus(Date date, long plus)
            throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(DATE_PATTERN);
        date = sdf.parse(sdf.format(date));
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        long time = cal.getTimeInMillis();
        long days = (plus) * (1000 * 3600 * 24);
        long time2 = time + days;

        Calendar cal2 = Calendar.getInstance();
        cal2.setTimeInMillis(time2);

        return cal2.getTime();
    }

    /**
     * Day add date.
     *
     * @param date   the date
     * @param field  the field
     * @param amount the amount
     * @return the date
     */
    public static Date dayAdd(Date date, int field, int amount) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(field, amount);
        return cal.getTime();
    }

    /**
     * Day sub date.
     *
     * @param date   the date
     * @param field  the field
     * @param amount the amount
     * @return the date
     */
    public static Date daySub(Date date, int field, int amount) {
        return dayAdd(date, field, -amount);
    }

    /**
     * Null safe method to check if it is on same day
     *
     * @param date1 the date 1
     * @param date2 the date 2
     * @return true if date1 and date2 is on same day, only Date part is consider, time part is ignored
     */
    public static Boolean isSameDay(Date date1, Date date2) {
        if (date1 == null && date2 == null) {
            return true;
        }
        if (date1 != null && date2 != null) {
            return DateUtils.isSameDay(date1, date2);
        }
        return false;
    }

    /**
     * 獲取本月的天數.
     *
     * @param date date
     * @return days month days
     */
    public static Integer getMonthDays(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * 獲取指定日期的后一天.
     *
     * @param date 指定日期
     * @return 指定日期的后一天 after day
     */
    public static Date getAfterDay(final Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 設置為后一天
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        return calendar.getTime();
    }

    /**
     * 獲取指定日期的后幾天.
     *
     * @param date 指定日期
     * @param days 天數
     * @return 指定日期的幾天 after day by org
     */
    public static Date getAfterDayByOrg(final Date date, final Integer days) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 設置為后一天
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    /**
     * 獲取指定日期的前一天.
     *
     * @param date 指定日期
     * @return 指定日期的前一天 before day
     */
    public static Date getBeforeDay(final Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        // 設置為前一天
        calendar.add(Calendar.DAY_OF_MONTH, -1);
        return calendar.getTime();
    }

    /**
     * 獲取星期幾.
     * <p>
     * 1:星期一，2:星期二，3:星期三，4:星期四，5:星期五，6:星期六，7:星期日，
     *
     * @param date 指定日期
     * @return Weekday weekday
     */
    public static Integer getWeekday(final Date date) {
        Integer weekday = weekday(date);
        if (weekday == 0) {
            weekday = 7;
        }
        return weekday;
    }

    /**
     * Gets weekday not iso.
     *
     * @param date the date
     * @return the weekday not iso
     */
    public static Integer getWeekdayNotIso(final Date date) {
        return weekday(date);
    }

    /**
     * Weekday integer.
     *
     * @param date the date
     * @return the integer
     */
    public static Integer weekday(final Date date) {
        final Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        return calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }

    /**
     * 判断该日期是否是该月的最后一天
     *
     * @param date 需要判断的日期
     * @return boolean boolean
     */
    public static boolean isLastDayOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH) == calendar
                .getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    /**
     * Local date to date date.
     *
     * @param localDate the local date
     * @return the date
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
        return Date.from(zdt.toInstant());
    }


    /**
     * Local date time to date date.
     *
     * @param localDate the local date
     * @return the date
     */
    public static Date localDateTimeToDate(LocalDateTime localDate) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDate.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }

    /**
     * Date to local date local date.
     *
     * @param date the date
     * @return the local date
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDate();
    }

    /**
     * Date to local date time local date time.
     *
     * @param date the date
     * @return the local date time
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        return instant.atZone(zoneId).toLocalDateTime();
    }

    /**
     * Gets time.
     *
     * @param localDate the local date
     * @return the time
     */
    public static Long getTime(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MIN).toEpochSecond(ZoneOffset.of("+8"));
    }

    /**
     * Gets time.
     *
     * @param localDateTime the local date time
     * @return the time
     */
    public static Long getTime(LocalDateTime localDateTime) {
        return localDateTime.toEpochSecond(ZoneOffset.of("+8"));
    }

    /**
     * Local date to local date time local date time.
     *
     * @param localDate the local date
     * @return the local date time
     */
    public static LocalDateTime LocalDateToLocalDateTime(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MIN);
    }

    /**
     * Local date time to local date local date.
     *
     * @param localDateTime the local date time
     * @return the local date
     */
    public static LocalDate LocalDateTimeToLocalDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate();
    }


    /**
     * 判断是否是周末.
     *
     * @param date 指定日期
     * @return boolean boolean
     */
    public static boolean isWeekend(final Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        final int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
        //0代表周日，6代表周六  
        if (week == 6 || week == 0) {
            return true;
        }
        return false;
    }

    public static String getWeekdayChinese(final LocalDate date) {
        String k = String.valueOf(date.getDayOfWeek());
        //获取行数
        for (String[] strings : strArray) {
            if (k.equals(strings[0])) {
                k = strings[1];
                break;
            }
        }
        return "星期" + k;
    }

    /**
     * Gets weekday.
     *
     * @param date the date
     * @return the weekday
     */
    public static Integer getWeekday(final LocalDate date) {
        DayOfWeek dayOfWeek = date.getDayOfWeek();
        if (dayOfWeek == DayOfWeek.MONDAY) {
            return 1;
        }

        if (dayOfWeek == DayOfWeek.TUESDAY) {
            return 2;
        }

        if (dayOfWeek == DayOfWeek.WEDNESDAY) {
            return 3;
        }

        if (dayOfWeek == DayOfWeek.THURSDAY) {
            return 4;
        }

        if (dayOfWeek == DayOfWeek.FRIDAY) {
            return 5;
        }

        if (dayOfWeek == DayOfWeek.SATURDAY) {
            return 6;
        } else {
            return 7;
        }

    }

    /**
     * Xml date 2 date date.
     *
     * @param cal the cal
     * @return the date
     */
    public static Date xmlDate2Date(XMLGregorianCalendar cal) {
        return cal.toGregorianCalendar().getTime();
    }

    /**
     * 根據出生日期計算年齡
     *
     * @param birthDate the birth date
     * @return age
     */
    public static int getAge(Date birthDate) {
        int age = 0;
        Calendar born = Calendar.getInstance();
        Calendar now = Calendar.getInstance();
        if (birthDate != null) {
            //當前系統時間
            now.setTime(new Date());
            born.setTime(birthDate);
            if (born.after(now)) {
                throw new IllegalArgumentException("The date of birth cannot exceed the current date!");
            }
            int nowYear = now.get(Calendar.YEAR);
            int bornYear = born.get(Calendar.YEAR);
            age = nowYear - bornYear;

            int nowMonth = now.get(Calendar.MONTH) + 1;
            int bornMonth = born.get(Calendar.MONTH) + 1;

            int nowDate = now.get(Calendar.DATE);
            int bornDate = born.get(Calendar.DATE);

            if (bornMonth > nowMonth) {
                age -= 1;
            } else if (bornMonth == nowMonth) {
                if (bornDate > nowDate) {
                    age -= 1;
                }
            }
        }
        return age;
    }

    /**
     * Gets time.
     *
     * @param date the date
     * @return the time
     */
    public static Long getTime(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getTime().getTime() / 1000;
    }

    /**
     * The entry point of application.
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
//        System.out.println(format(getFirstDayInMonth(2020, 1)));
//        System.out.println(format(getLastDayInMonth(2020, 1)));
//        System.out.println(LocalDate.now().plusYears(-2));
//        LocalDate now = LocalDate.now();
//        System.out.println(now.format();

    }

    /**
     * 将Date 和 HHmm格式时间拼接 dd/MM/yyy HH:mm
     *
     * @param date     the date
     * @param hhMMTime the hh mm time
     * @return date
     */
    public static Date joinDateAndHHmm(Date date, String hhMMTime) {
        if (date == null) {
            return null;
        }

        if (date != null && StringUtils.isBlank(hhMMTime)) {
            return date;
        }

        int hour = Integer.parseInt(hhMMTime.substring(0, 2));
        int minute = Integer.parseInt(hhMMTime.substring(2, 4));
        Date date1 = DateUtil.dayAdd(date, Calendar.HOUR, hour);
        Date joinDateTime = DateUtil.dayAdd(date1, Calendar.MINUTE, minute);

        return joinDateTime;
    }

    /**
     * 将日期集合拼接成字符串.
     *
     * @param availDateList availDateList
     * @return String string
     */
    public static String convertAvailDateListToString(List<Date> availDateList) {
        String returnValue = "";
        if (CollectionUtils.isEmpty(availDateList)) {
            return returnValue;
        }
        for (Date date : availDateList) {
            returnValue = String.format("%s%s", returnValue, DateUtil.format(date, DateUtil.DATE_SYSTEM_PATTERN));
        }
        return returnValue;
    }

    /**
     * 获取某年第一天日期
     *
     * @param year 年份
     * @return Date date
     */
    public static Date getYearFirst(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }


    /**
     * 获取某年最后一天日期
     *
     * @param year 年份
     * @return Date date
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        Date currYearLast = calendar.getTime();

        return currYearLast;
    }

    /**
     * 根据year ,month 返回当前year的month的第一天
     *
     * @param year  the year
     * @param month the month
     * @return first day in month
     */
    public static Date getFirstDayInMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date firstDayInMonth = calendar.getTime();
        return firstDayInMonth;

    }

    /**
     * 根据year ,month 返回当前year的month的最后一天
     *
     * @param year  the year
     * @param month the month
     * @return last day in month
     */
    public static Date getLastDayInMonth(int year, int month) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.set(Calendar.MONTH, month - 1);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        Date lastDayInMonth = calendar.getTime();
        return lastDayInMonth;
    }

    /**
     * get month short spell by locale Us
     *
     * @param month the month
     * @return short spell by us
     */
    public static String getShortSpellByUs(int month) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM");
        Date date = null;
        try {
            date = sdf.parse(month + "");
            sdf = new SimpleDateFormat("MMM", Locale.US);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        return sdf.format(date);
    }

    public static Set<Date> getDatesBetween(Date leaveStartDate, Date leaveEndDate) {
        Calendar tempStart = Calendar.getInstance();
        tempStart.setTime(leaveStartDate);

        Calendar tempEnd = Calendar.getInstance();
        tempEnd.setTime(leaveEndDate);
        Set<Date> days = new HashSet<>();
        tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
        while (tempStart.before(tempEnd)) {
            days.add(tempStart.getTime());
            tempStart.add(Calendar.DAY_OF_YEAR, 1);
        }
        return days;
    }


    /**
     * Year Month Day 转化 为 Date
     * @param year
     * @param month
     * @param day
     * @return
     */
    public static Date calendarToData(int year, int month, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, month - 1, day);//设置日历时间，月份必须减一
        Date date = calendar.getTime();
        return date;
    }

    /**
     * 获得只有 [年 月 日] 的Date 对象
     * @param date
     * @return
     */
    public static Date getYearMonthDayDate(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String sDate = simpleDateFormat.format(date);
        Date d = null;
        try {
            d = simpleDateFormat.parse(sDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return d;
    }
}
